﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TbaStarTest
{
    class Tile
    {
        public int X { get; set; }
        public int Y { get; set; }
        public int Type { get; set; } // 0 = nothing  1 = tile

        public bool IsStart { get; set; }
        public bool IsEnd { get; set; }
        public Tile Parent { get; set; }
        public HashSet<Tile> Adjacencies { get; set; }

        private TileMap tileMap;

        private double localCost; // cost of getting from this square to goal (the heuristic)
        private double parentCost; // cost of getting from parent square to this node
        private double passThroughCost;// cost of getting from the start to the goal
        // through this square

        /// <summary>
        /// Constructs a new Tile.
        /// </summary>
        /// <param name="x">X-position.</param>
        /// <param name="y">Y-position.</param>
        /// <param name="type">The type of this tile (0 for empty space, 1 for tile to 
        /// be collided with when executing the A*-algorithm.</param>
        /// <param name="tileMap">The tilemap.</param>
        public Tile(int x, int y, int type, TileMap tileMap)
        {
            this.X = x;
            this.Y = y;
            this.Type = type;
            this.tileMap = tileMap;
            this.Adjacencies = new HashSet<Tile>();
        }

        /// <summary>
        /// Calculates the adjacent tiles.
        /// </summary>
        public void CalculateAdjacencies()
        {
            int left = X - 1;
            int right = X + 1;
            int top = Y - 1;
            int bottom = Y + 1;

            // NOTE: We only need to check the right and bottom tiles, because the left and top tiles are
            // also set in the process by allocating this tile to the right or bottom tile. Basically this
            if (right < tileMap.Columns)
            {                            // rows, columns
                Tile rightTile = tileMap.Tiles[Y, right];
                if (rightTile.Type == 0) // No tile present at the left
                {
                    if (this.Type == 0)
                        rightTile.Adjacencies.Add(this); // Add this tile to the right tile's adjacencies
                                                        // THIS TILE IS THE LEFT TILE OF "rightTile"
                    this.Adjacencies.Add(rightTile); // Add the left tile to this tile's adjacencies
                }
            }

            if (bottom < tileMap.Rows)
            {
                Tile bottomTile = tileMap.Tiles[bottom, X];
                if (bottomTile.Type == 0) // No tile present at the bottom
                {
                    if (this.Type == 0)
                        bottomTile.Adjacencies.Add(this); // THIS TILE IS THE TOP TILE OF "bottomTile"
                    this.Adjacencies.Add(bottomTile);
                }
            }
        }

        public double getPassThrough(Tile goal)
        {

            if (this.IsStart)
            {
                return 0.0;
            }

            return getLocalCost(goal) + getParentCost();
        }

        public double getLocalCost(Tile goal)
        {

            if (this.IsStart)
            {
                return 0.0;
            }

            localCost = 1.0 * (Math.Abs(X - goal.X) + Math.Abs(Y - goal.Y));
            return localCost;
        }

        public double getParentCost()
        {

            if (this.IsStart)
            {
                return 0.0;
            }

            if (parentCost == 0.0)
            {
                parentCost = 1.0 + .5 * (Parent.getParentCost() - 1.0);
            }

            return parentCost;
        }
    }
}
